#include "StormLightning.h"
#include "EffectManager.h"
#include "Sprite.h"
#include "savage.h"
#include "ThorSceneManager.h"
#include "Scene.h"

extern OgreCanvas * gc;

StormLightning::StormLightning()
{
	cloudPosition = Ogre::Vector3(0,0,0);
	sparkPosition = cloudPosition + Ogre::Vector3(0,0,1.5);
	lightningPosition = cloudPosition + Ogre::Vector3(-0.25,0,6); //half size

	sparkTriggerTime = 2.0f;
	lightningTriggerTime = 3.0f;
	wholeInterval = 4.0f;

	mPlayingState = ASS_INACTIVE;
	originalCenter = Vector2::ZERO;
	allowedDistance2 = 17;
	allowedDistance = Math::Sqrt(allowedDistance2);
	cloudAveragePos = Vector2::ZERO;

	height = 0;
	speedOfCenterMoving = 0.8f;

	lightningHasRegisterVanish = false;



}
StormLightning::~StormLightning()
{

}

void StormLightning::load()
{
	//create animationSet
	m_pLightningAS = new AnimationSet(m_pSceneMgr);
	m_pLightningAS->AnimationSetCreate("0", "shandian", 10 , 1, 1);
	m_pLightningAS->setPosition(lightningPosition);
	m_pLightningAS->setDimension(Vector2(15,30));
	m_pLightningAS->setTimeInterval(60.0f/1000.0f);
	m_pLightningAS->setRenderQueueGroup(Ogre::RenderQueueGroupID(Ogre::RENDER_QUEUE_OVERLAY + 2));
	m_pLightningAS->setVisable(false);

	//particle
	Ogre::Vector3 _p3D = Ogre::Vector3(32,0,30);
	Ogre::ParticleSystem *tmpPtcSys = m_pSceneMgr->createParticleSystem("test",Ogre::String("PEExamples/BRLS"));
	mCloudNode = m_pSceneMgr->getRootSceneNode()->createChildSceneNode();
	mCloudNode->attachObject(tmpPtcSys);
	Ogre::ParticleEmitter*  m_pEmitter1  = tmpPtcSys->getEmitter(0);
	mCloudNode->setPosition(cloudPosition);
	//m_pEmitter1->setEmissionRate(60);
	m_pEmitter1->setEnabled(false);
	tmpPtcSys->setRenderQueueGroup(Ogre::RENDER_QUEUE_OVERLAY + 1);


	_p3D = Ogre::Vector3(32,0,38);
	tmpPtcSys = m_pSceneMgr->createParticleSystem("test1",Ogre::String("PEExamples/BRLS_lighting"));
	mSparkNode = m_pSceneMgr->getRootSceneNode()->createChildSceneNode();
	mSparkNode->attachObject(tmpPtcSys);
	m_pEmitter1  = tmpPtcSys->getEmitter(0);
	mSparkNode->setPosition(sparkPosition);
	//m_pEmitter1->setEmissionRate(60);
	m_pEmitter1->setEnabled(false);
	tmpPtcSys->setRenderQueueGroup(Ogre::RENDER_QUEUE_OVERLAY);
}


void StormLightning::update(Ogre::Real timeSinceLast)
{	
	if(!mEnabled)
		return;

	//when enabled, timer starts.
	timeSinceStartCloud += timeSinceLast;

	//now determine different period of this effect.
	if(timeSinceStartCloud >0)
	{
		((Ogre::ParticleSystem *)(mCloudNode->getAttachedObject(0)))
			->getEmitter(0)->setEnabled(true);

	}
	if(timeSinceStartCloud >sparkTriggerTime)
	{
		((Ogre::ParticleSystem *)(mSparkNode->getAttachedObject(0)))
			->getEmitter(0)->setEnabled(true);
		//cloud finished, then we can calculate the average position
		//but only calculate once
		if (cloudAveragePos == Vector2::ZERO && cloudPosCollection.size() > 0 )
		{
			Vector2 sum = Vector2::ZERO;
			for (unsigned int i = 0; i< cloudPosCollection.size(); i++)
			{
				sum += cloudPosCollection[i];
			}
			cloudAveragePos = sum / cloudPosCollection.size();
			Vector3 p3D = Sprite::_getInteractPosition3D(m_pCamera, cloudAveragePos,height);
			setPostionViaCloud(p3D,height);
		}

	}
	if(timeSinceStartCloud > lightningTriggerTime)
	{
		m_pLightningAS->play(timeSinceLast);
		m_pLightningAS->setVisable(true);
		if(!lightningHasRegisterVanish)
		{
			Ogre::Real params[10];
			params[0] = -8.0f;//a
			params[1] = 4.0f;//b
			params[2] = 0.0f;//c
			EffectManager::getInstance()->registerVanishPass(m_pLightningAS->getMaterialPass(),
				1.0f,EffectManager::VFT_PARA,params);
			
			params[0] = -32.0f;//a
			params[1] = 8.0f;//b
			params[2] = 0.0f;//b*/

			EffectManager::getInstance()->triggerFullScreenMaskVanish(Vector3(0.0f,0.0f,0.0f),
				0.25f,EffectManager::VFT_PARA,params);
			lightningHasRegisterVanish = true;
		}

		//need to effect the savages under it 
		Savage* SavageTmp =(Savage*)( ThorSceneManager::getInstance()->getCurrentScene()->getNPCSprite("savage1") );
		SavageTmp->shockedByLightning(2.0f);
		SavageTmp =(Savage*)( ThorSceneManager::getInstance()->getCurrentScene()->getNPCSprite("savage2") );
		SavageTmp->shockedByLightning(2.0f);

	}
	if(m_pLightningAS->reportOneRoundFinished())//timeSinceStartCloud > wholeInterval
	{
		stop();
	}

	//for debug
	if (hasBegun())
	{
		gc->setColor(0x88ffffff);
		gc->drawEllipse(
			originalCenter.x,
			originalCenter.y,
			Math::Sqrt(allowedDistance2),
			Math::Sqrt(allowedDistance2)/1.414f,
			10);
	}



}
void StormLightning::begin()
{
	EffectBase::begin();

	//reset state if begin
	timeSinceStartCloud = 0;
	cloudAveragePos = Vector2::ZERO;
	cloudPosCollection.clear();
	lightningHasRegisterVanish = false;

	m_pLightningAS->setVisable(false);
	m_pLightningAS->reset();

	((Ogre::ParticleSystem *)(mSparkNode->getAttachedObject(0)))
		->getEmitter(0)->setEnabled(false);
	((Ogre::ParticleSystem *)(mCloudNode->getAttachedObject(0)))
		->getEmitter(0)->setEnabled(false);

	setEnabled(true);
}

bool StormLightning::hasBegun()
{
	return mPlayingState == ASS_STARTED ? true:false;
}


void StormLightning::stop()
{
	EffectBase::stop();

	cloudAveragePos = Vector2::ZERO;
	cloudPosCollection.clear();

	timeSinceStartCloud = 0;
	setEnabled(false);
	((Ogre::ParticleSystem *)(mCloudNode->getAttachedObject(0)))
		->getEmitter(0)->setEnabled(false);
	((Ogre::ParticleSystem *)(mSparkNode->getAttachedObject(0)))
		->getEmitter(0)->setEnabled(false);

	m_pLightningAS->setVisable(false);

}

void StormLightning::setPostionViaCloud(Vector3 pos, Real _h)
{
	cloudPosition = pos;
	height = _h;
	sparkPosition = cloudPosition + Ogre::Vector3(0,0,0.75);
	lightningPosition = cloudPosition; //Ogre::Vector3(-10,0,height/1.414f); //half size


	m_pLightningAS->setPosition(lightningPosition);
	m_pLightningAS->setDimension(Vector2(height/2,height*0.8f));

	mCloudNode->setPosition(cloudPosition);
	mSparkNode->setPosition(sparkPosition);
}

void StormLightning::setOriginalCenter(Vector2 oc)
{
	originalCenter.x = oc.x;
	originalCenter.y = oc.y;
}

void StormLightning::eventMouseMove(int _x, int _y, int _xRel, int _yRel, bool isButtonDown)
{

}

void StormLightning::stateMouseDown(int _x, int _y, int _xRel, int _yRel, bool isButtonDown)
{
	Ogre::Vector3 p3D =  Sprite::_getInteractPosition3D(m_pCamera,Vector2(_x,_y), height);
	cloudPosition = p3D;
	mCloudNode->setPosition(cloudPosition);

	/*if(mPlayingState == ASS_INACTIVE)
	begin();*/

	//game specified logic
	//if move too far away from the original center,
	//then adjust back to the area
	Ogre::Real distance2 = 
		Ogre::Vector2(_x-originalCenter.x, (_y-originalCenter.y)*1.414f).squaredLength(); 
	Vector2 VecloudPosition2D = Vector2(_x,_y);
	if(distance2 > allowedDistance2)
	{
		//adjust within the distance
		//obtain slope first
		Real dx = _x-originalCenter.x;
		Real dy = _y-originalCenter.y;
		//first make original move slightly

		dx>0? 
			originalCenter.x += speedOfCenterMoving:originalCenter.x -= speedOfCenterMoving;
		dy>0?
			originalCenter.y += speedOfCenterMoving:originalCenter.y -= speedOfCenterMoving;


		//Real slope  = (_y-originalCenter.y) / (_x-originalCenter.x);
		VecloudPosition2D = Vector2(originalCenter.x + allowedDistance * (dx / Math::Sqrt(dx*dx + dy*dy)),
			originalCenter.y + allowedDistance * (dy / Math::Sqrt(dx*dx + dy*dy)));
		cloudPosition  = Sprite::_getInteractPosition3D(m_pCamera,VecloudPosition2D, height);		
		mCloudNode->setPosition(cloudPosition);		
	}

	if(timeSinceStartCloud >0)
	{
		//collect cloud pos in the past
		if(cloudPosCollection.size()>100)
		{
			//erase the first one and push back
			std::vector<Vector2>::iterator it = cloudPosCollection.begin();
			cloudPosCollection.erase(it);
		}
		cloudPosCollection.push_back(VecloudPosition2D);
	}
}

void StormLightning::eventMouseRelease(int _xx, int _yy)
{
	if (timeSinceStartCloud < sparkTriggerTime)
	{
		stop();
	}
}

